package cn.tedu.submarine;


import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

//整个游戏窗口
public class World extends JPanel {
    //窗口的宽
    public static final int HEIGHT = 479;

    //窗口的高
    public static final int WIDTH = 641;

    //运行状态
    public static final int RUNNING = 0;
    //暂停状态
    public static final int PAUSE =1;

    //游戏结束状态
    public static final int GAME_OVER = 2;
    private int state = RUNNING;//当前状态

    private Battleship ship = new Battleship();//战舰对象
    private SeaObject[] submarines = {};//潜艇数组
    private Mine[] mines = {};//水雷数组
    private Bomb[] bombs ={};//炸弹数组

    /**
     * 生成潜艇对象
     * @return 返回潜艇
     */
    private SeaObject nextSubmarine(){
        Random rand = new Random();
        int type = rand.nextInt(20);//随机0——19
        if(type <10){
            return new ObserveSubmarine();//0-9返回侦查潜艇
        }else if(type <16){
            return new TorpedoSubmarine();//10-15 返回鱼类潜艇
        }else {
            return new MineSubmarine();//返回水雷潜艇对象
        }
    }
    private int subEnterIndex = 0;//潜艇入场计数

    //潜艇入场
    private void submarineEnterAction(){//每10毫秒走一次
        subEnterIndex++;//每10毫秒增1
        if (subEnterIndex % 40 == 0) {//每400(40*10)毫秒走一次S
            SeaObject obj = nextSubmarine();//获取潜艇对象
            submarines = Arrays.copyOf(submarines,submarines.length+1);
            submarines[submarines.length-1] = obj;//将obj添加到submarine
        }
    }
    private int mineEnterIndex = 0; //水雷入场计数

    /**
     *水雷入场
     */
    private void mineEnterAction() {
        mineEnterIndex++;//每10毫秒怎个1；
        if (mineEnterIndex % 100 == 0) {//每1000毫秒走一次
            for (int i = 0; i < submarines.length; i++) {
                if (submarines[i] instanceof MineSubmarine) {//若潜艇为水雷潜艇
                    MineSubmarine ms = (MineSubmarine) submarines[i];//讲潜艇转换为水雷潜艇
                    Mine obj = ms.shootMine();//获取水雷对象
                    mines = Arrays.copyOf(mines, mines.length + 1);//扩容
                    mines[mines.length - 1] = obj;//将obj添加到mines最后一个元素

                }
            }
        }
    }
    /**
     * 海洋对象移动
     */
    private void moveAction(){ //每10毫秒走一次
        for(int i=0;i<submarines.length;i++){ //遍历所有潜艇
            submarines[i].move(); //潜艇动
        }
        for(int i=0;i<mines.length;i++){ //遍历所有水雷
            mines[i].move(); //水雷动
        }
        for(int i=0;i<bombs.length;i++){ //遍历所有炸弹
            bombs[i].move(); //炸弹动
        }
    }
    /**
     * 删除越界的海洋对象，意义:避免内存泄漏
     */
    private void outOfBoundsAction(){ //每10毫秒走一次
        for(int i=0;i<submarines.length;i++){ //遍历所有潜艇
            if(submarines[i].isOutOfBounds() || submarines[i].isDead()){ //若越界了或死了的
                submarines[i] = submarines[submarines.length-1]; //将越界元素替换为最后一个元素
                submarines = Arrays.copyOf(submarines,submarines.length-1); //缩容
            }
        }
        for(int i=0;i<mines.length;i++){ //遍历所有水雷
            if(mines[i].isOutOfBounds() || mines[i].isDead()){ //若越界了或死了的
                mines[i] = mines[mines.length-1]; //将越界元素替换为最后一个元素
                mines = Arrays.copyOf(mines,mines.length-1); //缩容
            }
        }
        for(int i=0;i<bombs.length;i++){ //遍历所有炸弹
            if(bombs[i].isOutOfBounds() || bombs[i].isDead()){ //若越界了或死了的
                bombs[i] = bombs[bombs.length-1]; //将越界元素替换为最后一个元素
                bombs = Arrays.copyOf(bombs,bombs.length-1); //缩容
            }
        }
    }
    private int score = 0; //玩家的得分

    /**
     * 炸弹与潜艇的碰撞
     */
    private void bombBangAction(){ //每10毫秒走一次
        for(int i=0;i<bombs.length;i++){ //遍历所有炸弹
            Bomb b = bombs[i]; //获取每一个炸弹
            for(int j=0;j<submarines.length;j++){ //遍历所有潜艇
                SeaObject s = submarines[j]; //获取每一个潜艇
                if(b.isLive() && s.isLive() && s.isHit(b)){ //若都活着并且还撞上了
                    s.goDead(); //潜艇去死
                    b.goDead(); //炸弹去死
                    if(s instanceof EnemyScore){ //若被撞潜艇为分
                        EnemyScore es = (EnemyScore)s; //将被撞潜艇强转为分的接口
                        score += es.getScore(); //玩家得分
                    }
                    if(s instanceof EnemyLife){ //若被撞潜艇为命
                        EnemyLife el = (EnemyLife)s; //将被撞潜艇强转为命的接口
                        int num = el.getLife(); //获取命数
                        ship.addLife(num); //战舰增命
                    }
                }
            }
        }
    }
            //检测水雷和战舰的碰撞
    private void mineBangAction(){
        for(int i=0;i<mines.length;i++){ //遍历所有水雷
            Mine m = mines[i]; //获取每一个水雷
            if(m.isLive() && ship.isLive() && m.isHit(ship)){ //若都活着并且还撞上了
                m.goDead(); //水雷去死
                ship.subtractLife(); //战舰减命
            }
        }
    }

    //检测游戏结束
    private void checkGameOverAction(){
        if(ship.getLife()<=0){ //若战舰的命数<=0，表示游戏结束了
            state = GAME_OVER; //将当前状态修改为游戏结束状态
        }
    }

    /**
     * 重写paint()画
     * @param g 系统自带的画笔
     */
    public void paint(Graphics g){ //每10毫秒走一次
        Images.sea.paintIcon(null,g,0,0); //画海洋图
        ship.paintImage(g); //画战舰
        for(int i=0;i<submarines.length;i++){ //遍历所有潜艇
            submarines[i].paintImage(g); //画潜艇
        }
        for(int i=0;i<mines.length;i++){ //遍历所有水雷
            mines[i].paintImage(g); //画水雷
        }
        for(int i=0;i<bombs.length;i++){ //遍历所有炸弹
            bombs[i].paintImage(g); //画炸弹
        }
        g.drawString("SCORE: "+score,200,50);         //画分----不要求掌握
        g.drawString("LIFE: "+ship.getLife(),400,50); //画命----不要求掌握

        if(state==GAME_OVER){ //若当前为游戏结束状态
            Images.gameover.paintIcon(null,g,0,0);
        }
    }
    /**
     * 启动程序的执行
     */
    private void action(){
        KeyAdapter k = new KeyAdapter() {
            /** 重写keyReleased()按键抬起事件 */ //keyPressed()按下事件
            public void keyReleased(KeyEvent e) { //不要求掌握--当按键抬起时会自动触发
                if(e.getKeyCode()==KeyEvent.VK_P){ //不要求掌握--若抬起的是P键
                    if(state==RUNNING){ //运行状态时修改为暂停状态
                        state = PAUSE;
                    }else if(state==PAUSE){ //暂停状态时修改为运行状态
                        state = RUNNING;
                    }
                }

                if(state==RUNNING){ //仅在运行状态时执行
                    if(e.getKeyCode()==KeyEvent.VK_SPACE){ //不要求掌握---若抬起的是空格键
                        Bomb obj = ship.shootBomb(); //获取炸弹对象
                        bombs = Arrays.copyOf(bombs,bombs.length+1); //扩容
                        bombs[bombs.length-1] = obj; //将obj添加到最后一个元素上
                    }
                    if(e.getKeyCode()==KeyEvent.VK_LEFT){ //不要求掌握--若抬起的是左箭头
                        ship.moveLeft(); //战舰左移
                    }
                    if(e.getKeyCode()==KeyEvent.VK_RIGHT){ //不要求掌握--若抬起的是右箭头
                        ship.moveRight(); //战舰右移
                    }
                }
            }
        };
        this.addKeyListener(k); //不要求掌握

        java.util.Timer timer = new Timer(); //定时器对象
        int interval = 10; //定时间隔(以毫秒为单位)
        timer.schedule(new TimerTask() {
            public void run() { //定时干的事----每10毫秒自动执行
                if(state==RUNNING){ //仅在运行状态时执行
                    submarineEnterAction(); //潜艇入场
                    mineEnterAction();      //水雷入场
                    moveAction();           //海洋对象移动
                    outOfBoundsAction();    //删除越界的海洋对象
                    bombBangAction();       //炸弹与潜艇的碰撞
                    mineBangAction();       //水雷与战舰的碰撞
                    checkGameOverAction();  //检测游戏结束
                    repaint(); //重画----系统自动调用paint()方法
                }
            }
        }, interval, interval); //定时计划表
    }
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        World world = new World(); //会创建窗口中的那一堆对象
        world.setFocusable(true);
        frame.add(world);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(WIDTH+16, HEIGHT+40);
        frame.setLocationRelativeTo(null);
        frame.setResizable(false);
        frame.setVisible(true); //自动调用paint()方法

        world.action(); //启动程序的执行
    }
}
